<template>
  <div class="operatorInfo">
    <div v-if="store.selectedId" class="operator-container">
      <el-tabs :key="tabsKey" v-model="activeName" class="tighten-tabs" :stretch="!rightDrawerExpanded"
        @tab-change="handleClick">
        <template v-if="!rightDrawerExpanded">
          <el-tab-pane label="参数" name="parameter" />
          <el-tab-pane label="信息" name="runInfo" />
        </template>
        <el-tab-pane label="日志" name="runLog" />
        <el-tab-pane label="运行结果" name="runResult" />
        <!-- <el-tab-pane v-for="rowFile in storagesList" :key="rowFile.key" :label="rowFile.label" :name="rowFile.key" /> -->
      </el-tabs>
      <div class="interval-container" :class="{ 'interval-parameter': activeName === 'parameter' }">
        <div v-show="activeName === 'parameter'" class="parameter">
          <el-form ref="nodeFormDom" :model="nodeForm" :rules="rulesRef" label-position="top" @submit.prevent>
            <el-collapse v-model="collapseValue">
              <el-collapse-item v-for="(rowForm, index) in formConfig" :key="'rowForm' + index" class="row-form-container"
                :name="rowForm.label" required="true">
                <template #title>
                  <span class="row-form-title">{{ rowForm.label }}
                    <el-tooltip class="box-item" effect="light " :content="rowForm.description" placement="right-start">
                      <el-button
                        style="transform: scale(.7);transform-origin:left ; margin:0 0 0 0px; font-size: 18px;color: #333;border-color: #333;"
                        size="small" circle>?
                      </el-button>
                    </el-tooltip>
                  </span>
                </template>
                <el-form-item>
                  <el-input v-if="rowForm.ui_type == 'input'" v-model="nodeForm.configs[index].value"
                    :placeholder="rowForm.description || ('请填写' + rowForm.label)" :readonly="readonly"
                    @change="updateNodeData(rowForm)" />
                  <upload-folder v-if="rowForm.ui_type == 'file'" :operatorData="rowForm" @successFileUrl="successFileUrl"
                    @deleteFile="deleteFile" />
                  <el-select v-if="rowForm.ui_type == 'featureset'" v-model="nodeForm[rowForm.name]" class="m-2"
                    placeholder="请选择特征集" v-load-more="getMoreData" :disabled="readonly"  popper-class="more_dropdown_select" >
                    <el-option v-for="item in optionsList" :key="item.title" :label="item.title" :value="item.id"
                      @click="selectOption(rowForm)" />
                    <div v-if="loadingMoreState" class="selectMoreData">
                      <el-icon class="is-loading">
                        <Loading />
                      </el-icon>加载更多
                    </div>
                  </el-select>
                  <el-radio-group v-if="rowForm.ui_type == 'radio'" v-model="rowForm.value" @change="operatorInitial"
                    :disabled="readonly">
                    <el-radio v-for="raduiItem in rowForm.options " :key="raduiItem.id" :label="raduiItem.value">{{
                      raduiItem.label }}</el-radio>
                  </el-radio-group>
                  <el-checkbox-group v-if="rowForm.ui_type == 'checkbox'" v-model="rowForm.chooseData"
                    @change="operatorInitial" :disabled="readonly">
                    <el-checkbox v-for="raduiItem in rowForm.options " :key="raduiItem.id" :label="raduiItem.value">
                      {{ raduiItem.label }}
                    </el-checkbox>
                  </el-checkbox-group>
                </el-form-item>
              </el-collapse-item>
            </el-collapse>
          </el-form>
          <el-empty v-if="formConfig.length === 0" description="暂无参数配置" />
        </div>
        <div v-show="activeName === 'runInfo'" class="runInfo form-container">
          <el-collapse v-model="runInfoActive">
            <el-collapse-item name="runInfo">
              <template #title>
                <span class="collapse-title">运行状态</span>
              </template>
              <el-form label-width="40px" label-position="left">
                <el-form-item label="名称">
                  {{ operatorData.label }}
                </el-form-item>
                <el-form-item label="状态">
                  <el-tag v-if="node && node.data.status"
                    :type="(instancesStateColor as any)[node.data.status.replace(/( |^)[a-z]/g, (L: any) => L.toUpperCase())]">{{
                      (instancesStateText as any)[node.data.status.replace(/( |^)[a-z]/g, (L: any) => L.toUpperCase())]
                    }}</el-tag>
                  <span v-else>无</span>
                </el-form-item>
              </el-form>
            </el-collapse-item>
            <el-collapse-item name="desc">
              <template #title>
                <span class="collapse-title">算子描述</span>
              </template>
              <el-input v-model="nodeDesc" class="node-desc" type="textarea" :autosize="{ minRows: 2 }"
                :placeholder="readonly ? '' : '请填写算子描述'" :readonly="readonly" @change="updateNodeDesc" />
            </el-collapse-item>
            <el-collapse-item name="explain">
              <template #title>
                <span class="collapse-title">算子信息</span>
              </template>
              <algo-info :node-data="nodeData" />
            </el-collapse-item>
          </el-collapse>
        </div>
        <div v-if="isInstance" v-show="runInfoShow || explorerState" class="instance-container">
          <operator-log v-show="activeName === 'runLog'" ref="operatorLog" :id-config="idConfig" />
          <operation-result v-show="activeName === 'runResult'" ref="operationResultRef" :id-config="idConfig" />
          <!-- <file-explorer-group v-show="explorerState" ref="fileExplorerGroup" :id-config="idConfig"
            :storages="storages" /> -->
        </div>
        <el-empty v-else-if="emptyShow" description="暂未运行" />
      </div>
    </div>
    <el-empty v-else description="请选择一个算子节点" />
    <column-handle-dialog v-if="columnHandleDialogVisible" ref="columnHandleDialog"
      v-model.visible="columnHandleDialogVisible" :id-config="idConfig"
      @updateTargetColumnData="updateTargetColumnData" />
    <!-- <context-menu-dialog v-if="contextMenuDialogVisible" ref="contextMenuDialog"
      v-model.visible="contextMenuDialogVisible" :id-config="idConfig" :storages="storages" /> -->
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, nextTick, watch, reactive } from "vue"
import { designerStore } from 'src/stores/designerTool/designerTool'
import AlgoInfo from '../DagEdit/components/AlgoInfo/index.vue'
import { instancesStateColor, instancesStateText, questionMark } from 'src/utils/designerTool/constants'
import FileExplorerGroup from './fileExplorerGroup.vue'
import { copyText, descriptionHandle, operatorValidatorForm } from 'src/utils/designerTool/toole'
import { isNull, isObject, isUndefined } from 'src/utils/designerTool/validate'
import ColumnHandleDialog from './columnHandleDialog.vue'
import OperatorLog from './operatorLog.vue'
import ContextMenuDialog from './contextMenuDialog.vue'
import OperationResult from './operationResult.vue'
import DynamicParameterBlock from './dynamicParameterBlock.vue'
import UploadFolder from './uploadFolder.vue'
import dagGraph from 'src/pages/designerTool/canvas/DagEdit/graph/index.js'
import vLoadMore from 'src/utils/loadMore'
import { getFeatureset } from 'src/api/dataset'
const props = defineProps({
  rightDrawerExpanded: {
    type: Boolean
  }
})
const store = designerStore()
const operatorInfoLoading = ref(false)
const idConfig = ref({
  workflowInfoId: '',
  instanceId: '',
  operator_id: '',
  node_id: '',
  experiment_id: ''
})
const storages = ref([
  {
    key: 'artifact',
    label: '文件',
    state: false
  },
  {
    key: 'data',
    label: '数据',
    state: false
  },
  {
    key: 'model',
    label: '模型',
    state: false
  }
])
// interface objectType {
//   [key: string]: string | number | undefined | null | void | object
// }
const nodeForm = ref(<Record<string, any>>{})
const nodeOtherData = ref(<Record<string, any>>{})
const rulesRef = ref({})
const node = ref<any>(null)
const activeName = ref('parameter')
const formConfig = ref(<any>[])
const operatorData = ref(<Record<string, any>>{})
const columnHandleDialogVisible = ref(false)
const tabsKey = ref(0)
const contextMenuDialogVisible = ref(false)
const collapseValue = ref([])
const runInfoActive = ref(['runInfo', 'desc', 'explain'])
const nodeDesc = ref('')
const nodeFormDom = ref<any>(null)
const columnHandleDialog = ref<any>(null)
const operatorLog = ref<any>(null)
const operationResultRef = ref<any>(null)
const fileExplorerGroup = ref<any>(null)
const contextMenuDialog = ref<any>(null)
const selectValue = ref('')
const pageData = ref({
  page: 1
})
const allAlg = ref({
  count: 0,
  results: <any>[]
})
const optionsList = ref(<any>[])
const loadingMoreState = ref(false)
const nodeData = computed(() => {
  return store.selectedId && node.value ? store.categoriesSubset[node.value.data.id] : {}
})
const isInstance = computed(() => {
  return readonly.value || (store.workflowInfo.id && store.instanceId)
})
const storagesList = computed(() => {
  return storages.value.filter(item => item.state)
})
const explorerState = computed(() => {
  return activeName.value === storages.value[0].key ||
    activeName.value === storages.value[1].key ||
    activeName.value === storages.value[2].key
})
const emptyShow = computed(() => {
  return !isInstance.value && (
    runInfoShow.value || explorerState.value
  )
})
const runInfoShow = computed(() => {
  return activeName.value === 'runLog' ||
    activeName.value === 'runResult'
})
const viewVersion = computed(() => {
  return !!store.versionId
})
const viewExperiment = computed(() => {
  return !store.LeftTabsState
})
// const viewExperiment = computed(() => {
//   return !!store.experimentId || !!store.flowReadonlyId
// })
const readonly = computed(() => {
  return viewVersion.value || viewExperiment.value
})
watch(() => store.selectedId, (newdata, oldData) => {
  activeName.value = 'parameter'
  initData()
})
watch(() => store.saveDag, (newdata, oldData) => {
  init()
})
watch(() => props.rightDrawerExpanded, (newData, oldData) => {
  if (newData) {
    switch (activeName.value) {
      case 'parameter':
      case 'runInfo':
        activeName.value = 'runLog'
        handleClick()
        break
      default:
    }
  } else {
    activeName.value = 'parameter'
  }
  setTimeout(() => {
    tabsKey.value++
  }, 100)
})
onMounted(() => {
  init()
})
copyText
function init() {
  initData()
}
function initData() {
  resetData()
  if (store.selectedId) {
    nodeClick()
    getInstancesResults()
  }

}
const emits = defineEmits(['updateHeadInfo', 'updateDrawerExpanded'])
function nodeClick() {
  optionsList.value = []
  pageData.value.page = 1
  node.value = dagGraph.graph?.getCellById(store.selectedId)
  if (store.allOperator.length > 0) {
    let operator_id = 0
    store.allOperator.forEach((ele: any) => {
      if (ele.node_id == store.selectedId) {
        operator_id = ele.id
      }
    })
    store.operator_id = operator_id
  }
  if (store.selectedId) {
    if (node.value && node.value.shape === 'vue-shape') {
      nodeDesc.value = node.value.data.desc
      switch (node.value.component) {
        case 'algo-node': {
          const nodeData = store.categoriesSubset[node.value.data.id]
          if (node.value.data.name == undefined) {
            node.value.data = Object.assign(node.value.data, nodeData)
          }
          console.log('node.value',node.value)
          let operatorStore = {
            data: nodeData
          }
          store.SET_OPERATOR_DATA(operatorStore)
          // emits('updateHeadInfo', nodeData)
          const rules = {}
          rulesRef.value = rules
          nodeForm.value = node.value.data
          formConfig.value = node.value.data.configs
          operatorInitial()
          formConfig.value.forEach((ele: any, index: number) => {
            if (ele.ui_type == 'featureset') {
              chooseFeatureset()
            }
          })
          let nameArr = nodeData.configs.map((item: any, index: number) => {
            return item.label
          })
          collapseValue.value = nameArr
          // nextTick(() => {
          //   formValidate(null)
          // })
          break
        }
        case 'text-node':
          // {
          //   label: '文本框',
          //   value: node.data.value
          // }
          break
        case 'algo-group':
          // {
          //   label: '算子群组',
          //   value: node.data.title
          // }
          break
        default:
      }
    }
  }
}
function operatorInitial() {
  formConfig.value.forEach((ele: any, index: number) => {
    if (ele.ui_type == 'input') {
      if (ele.default_value == null) {
        nodeForm.value.configs[index].value = ''
        nodeForm.value.configs[index].value = saveDagTidy(ele.id.toString())
      } else {
        nodeForm.value.configs[index].value = ele.default_value
      }
    }
    if (ele.ui_type === 'radio' && ele.value === undefined) {
      nodeForm.value.configs[index].value = ele.default_value;
    }

    if (ele.ui_type == 'checkbox') {
      if (ele.value == undefined) {
        nodeForm.value.configs[index].chooseData = ele.default_value.split(',')
      }
      nodeForm.value.configs[index].value = nodeForm.value.configs[index].chooseData.join()
    }
  })
}

// 输入路径数据处理
function saveDagTidy(port_id: string) {
  let str = null
  let selectData = <any>[]
  store.saveDag.cells.forEach((cellsEle: any, index: number) => {
    if (cellsEle.shape === 'edge') {
      if (cellsEle.target.cell == node.value.id) {
        selectData.push(cellsEle)
      }
    }
  })
  selectData.forEach((selectEle: any, index: number) => {
    if (selectEle.target.port == port_id) {
      store.saveDag.cells.forEach((cellsEle: any, index: number) => {
        if (selectEle.source.cell == cellsEle.id) {
          cellsEle.data.configs.forEach((outData: any) => {
            if (outData.param_type == 'output' && selectEle.source.port == outData.id) {
              str = outData.default_value
            }
          })
        }
      })
    }
  })
  return str
}


function resetData() {
  nodeForm.value = {}
  rulesRef.value = {}
  nodeFormDom.value.clearValidate()
  node.value = null
  formConfig.value = []
  operatorData.value = {}
  storages.value.forEach(row => {
    row.state = false
  })
}
// 文件上传数据处理
function successFileUrl(e: any) {
  nodeForm.value[e.name] = e.default_value
  const data = node.value.getData()
  data.configs = formConfig.value
  data.configs.forEach((ele: any) => {
    if (ele.name == e.name) {
      ele.value = e.default_value
    }
  })
}
// 删除文件
function deleteFile(e: any) {

  const data = node.value.getData()
  data.configs = formConfig.value
  data.configs.forEach((ele: any) => {
    if (ele.name == e.name) {
      delete ele.value
      ele.default_value = null
    }
  })
  formConfig.value = data.configs
}
// const marginTest = () => {
//   console.log('margin test')
// }
function updateNodeData(item: any) {
  const data = node.value.getData()
  data.configs = formConfig.value
  data.configs.forEach((ele: any, index: number) => {
    if (ele.name == item.name) {
      ele.value = nodeForm.value.configs[index].value
      ele.default_value = nodeForm.value.configs[index].value
    }
  })
  node.value.setData({
    ...data
  })
  // formValidate(item.name)
}


function uploadSuccessFunc(item: any, value: any) {
  let url = ''
  let name = ''
  for (const key in value) {
    url = value[key].url
    name = value[key].name
  }
  nodeForm.value[item.name] = url
  let other
  if (name) {
    other = { name }
  }
  nodeOtherData.value[item.name] = other
  updateNodeData(item)
}
function deleteFileName(item: any) {
  uploadSuccessFunc(item, {})
}
function fileNameHandle(key: string) {
  const other = nodeOtherData.value[key]
  if (other && isObject(other) && other.name) {
    return other.name
  } else {
    const fileUrl = nodeForm.value[key]
    const fileSplit = fileUrl.split('/')
    if (fileSplit.length) {
      const fileName = fileSplit[fileSplit.length - 1]
      return fileName.includes('?') ? fileName.substring(0, fileName.indexOf('?')) : fileName
    } else {
      return fileUrl
    }
  }
}

function updateRadioCustom(item: any, value: any) {
  nodeForm.value[item.name] = value
  updateNodeData(item)
}
function updateCheckboxCustom(item: any, value: any) {
  const checkboxValue = <any>[]
  if (value && value.length) {
    item.ui_config.options.forEach((row: any) => {
      if (value.indexOf(row.label) !== -1) {
        checkboxValue.push(row.value)
      }
    })
  }
  updateNodeData(item)
}
function getInstancesResults() {
  idConfig.value.workflowInfoId = store.workflowInfo.id
  idConfig.value.instanceId = store.instanceId
  idConfig.value.operator_id = node.value.data.id
  idConfig.value.node_id = store.selectedId
  if (store.experimentId) {
    idConfig.value.experiment_id = node.value.data.experiment_id
  }
  const categoriesData = store.categoriesSubset[idConfig.value.operator_id]
  storages.value.forEach((row: any) => {
    row.state = true

    // row.state = !!categoriesData.storages[row.key]

  })
  operatorData.value = {
    label: categoriesData.label
  }
}
function updateDynamicParameter(index: any, itemIndex: number, item: any) {
  let inputs = ''
  if (nodeData.value?.inputs && nodeData.value.inputs.length) {
    inputs = nodeData.value.inputs[0].name
  }
  const configsData = node.value.data.configs[item.typeKey]
  let data = {}
  // && row.value.workflowId
  configsData.forEach((row: any) => {
    if (row.name === item.name) {
      data = row.value
    }
  })
  columnHandleDialogVisible.value = true
  nextTick(() => {
    columnHandleDialog.value.init({
      index: [index, itemIndex],
      operator_id: node.value.data.id,
      node_id: node.value.id,
      data: JSON.parse(JSON.stringify(data)),
      input: (item.ui_config && item.ui_config.input) ? item.ui_config.input : inputs,
      component: item.component,
      label: item.label,
      ui_config: item.ui_config,
      value_type: item.value_type_code,
      componentGroup: item.componentGroup
    })
  })
}
function updateTargetColumnData(componentData: any) {
  const item = formConfig.value[componentData.index[0]].data[componentData.index[1]]
  nodeForm.value[item.name] = componentData.form
  updateNodeData(item)
}

function handleClick() {
  if (isInstance.value) {
    switch (activeName.value) {
      case 'runLog':
        operatorLog.value.init()
        updateDrawerExpanded()
        break
      case 'runResult':
        operationResultRef.value.init()
        updateDrawerExpanded()
        break
      case storages.value[0].key:
      case storages.value[1].key:
      case storages.value[2].key:
        fileExplorerGroup.value.init(activeName.value)
        updateDrawerExpanded()
        break
      default:
    }
  }
}

function updateDrawerExpanded() {
  if (!props.rightDrawerExpanded) {
    emits('updateDrawerExpanded', true)
  }
}
function updateNodeDesc(value: any) {
  const data = node.value.getData()
  node.value.setData({
    ...data,
    desc: value
  })
}
function parentUpdateStoragesState(str: any) {
  if (str === 'runLog' || str === 'runResult') {
    activeName.value = str
    handleClick()
  } else {
    storages.value.forEach((row: any) => {
      if (row.key === str && row.state) {
        activeName.value = str
        handleClick()
      }
    })
  }
}
function openContextMenuDialog(type: any) {
  contextMenuDialogVisible.value = true
  nextTick(() => {
    contextMenuDialog.value.init(type)
  })
}
// function formValidate(name: any) {
//   console.log()
// if (name) {
//   nodeFormDom.value.validateField(name)
// } else {
//   nodeFormDom.value.validate((valid) => {
//     return false
//   })
// }
// }
function chooseFeatureset() {
  getFeatureset(store.project_id, pageData.value).then((res: any) => {
    allAlg.value = res.data
    optionsList.value = optionsList.value.concat(allAlg.value.results)
    loadingMoreState.value = false
    selectValue.value = store.selectOptionStr
  }).catch(error => {
    console.log(error)
  })
}

const getMoreData = async () => {
  if (pageData.value.page < (allAlg.value.count) / 10) {
    loadingMoreState.value = true
    pageData.value.page++
    chooseFeatureset()
  }
}

function selectOption(item: any) {
  if (selectValue.value.length > 0) {
    store.SELECT_OPTION_STR(selectValue.value)
  }
  const data = node.value.getData()
  data.configs = formConfig.value
  data.configs.forEach((ele: any) => {
    if (ele.name == item.name) {
      ele.value = nodeForm.value[item.name]
    }
  })
  // const data = node.value.getData()
  // data.configs = formConfig.value
  // data.configs[0].value=selectValue.value
}

function filterData(arr: Array<any>) {
  let nameStr = ''
  arr.forEach(element => {
    if (element.split_file == selectValue.value) {
      nameStr = element.title
    }
  })
  return nameStr
}
defineExpose({ openContextMenuDialog, parentUpdateStoragesState })

</script>

<style lang="scss" scoped>
@import "src/css/designerStyles/index.scss";

.operatorInfo {
  height: calc(100% - 36px);

  .interval-title {
    padding: 9px;
    line-height: 16px;
    text-align: center;
    background: #fff;
    border-bottom: 1px solid #dcdee2;

    &.interval-title-top-border {
      border-top: 1px solid #dcdee2;
    }
  }

  .interval-container {
    position: relative;
    height: calc(100% - 40px);
    overflow-y: auto;
    overflow-x: hidden;
    padding: 8px 4px;

    ::v-deep.el-collapse {
      border: 0;

      .el-collapse-item__header {
        border-bottom: 1px solid $--color-blue;
        height: 38px;
        line-height: 38px;
      }

      .el-collapse-item__wrap {
        border: 0;
      }

      .el-collapse-item__content {
        padding: 0;
      }

      .el-form-item {
        margin-bottom: 18px;

        .el-checkbox-group {
          line-height: 1;
        }

        .el-form-item__label {
          width: 100%;
          display: flex;
        }

        &.padding-right-50 {
          .el-form-item__label {
            padding-right: 50px;
          }
        }

        &.readonly {
          .el-input-number {
            .el-input__inner {
              cursor: default;
              background-color: #FFF;
              border-color: #DCDFE6;
              color: #606266;
            }
          }

          .el-radio {
            cursor: default;

            .el-radio__input {
              cursor: default;
            }

            .el-radio__input.is-disabled .el-radio__inner {
              cursor: default;
              background-color: #FFF;
              border-color: #DCDFE6;
            }

            .el-radio__input.is-checked.is-disabled .el-radio__inner {
              border-color: $--color-blue;
              background: $--color-blue;
            }

            .el-radio__input.is-disabled.is-checked .el-radio__inner::after {
              cursor: default;
              background-color: #FFF;
            }

            .el-radio__input.is-disabled+span.el-radio__label {
              color: #606266;
              cursor: default;
            }
          }

          .el-slider {
            .el-slider__runway.disabled .el-slider__bar {
              background-color: $--color-blue;
            }

            .el-slider__runway.disabled .el-slider__button {
              border-color: $--color-blue;
            }
          }

          .el-checkbox {
            cursor: default;
          }

          .el-checkbox-group {
            .el-checkbox__input.is-disabled .el-checkbox__inner {
              background-color: #FFF;
              border-color: #DCDFE6;
              cursor: default;
            }

            .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after {
              border-color: #FFF;
            }

            .el-checkbox__input.is-checked.is-disabled .el-checkbox__inner {
              background-color: $--color-blue;
              border-color: $--color-blue;
            }

            .el-checkbox__input.is-disabled+span.el-checkbox__label {
              color: #606266;
              cursor: default;
            }

            .el-checkbox__input.is-disabled.is-checked+span.el-checkbox__label {
              color: $--color-blue;
              cursor: default;
            }
          }

          .el-select {
            .el-input.is-disabled .el-input__inner {
              background-color: #FFF;
              border-color: #DCDFE6;
              color: #606266;
              cursor: default;
            }

            .el-input__suffix {
              display: none;
            }

            .el-input--suffix .el-input__inner {
              padding-right: 15px;
            }
          }
        }

        &.is-error {
          .dynamicParameterBlock {
            .config-list {
              border-color: #F56C6C;

              .not-data {
                color: #F56C6C;
              }
            }
          }
        }
      }
    }

    .row-form-container {
      .row-form-title {
        font-size: 14px;
        font-weight: 600;
        width: 100%;
        display: block;
        padding-bottom: 4px;
        line-height: 1.2;
      }

      .form-item-tooltip {
        margin-left: 8px;
        color: #606266;
      }

      .el-input-number {
        width: 100%;
      }

      .el-select {
        width: 100%;
      }
    }

    ::v-deep.from-slider {
      .el-slider {
        display: flex;
        flex-direction: column-reverse;

        &.full-load {
          .el-input-number {
            width: 100%;
          }
        }
      }

      .el-slider__input {
        float: unset;
      }

      .el-slider__runway.show-input {
        margin: 16px 8px;
      }
    }

    .slider-range {
      display: flex;
      flex-direction: column;

      .input-number {
        position: relative;
        width: 100%;

        .el-input-number {
          width: 130px;
        }
      }

      .separator {
        width: 130px;
        text-align: center;
      }

      &.full-load {
        .el-input-number {
          width: 100%;
        }

        .separator {
          width: 100%;
        }
      }
    }

    .unitText {
      position: absolute;
      right: 0;
      bottom: 0;
      width: 128px;
      text-align: center;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .radio-component {
      margin-bottom: -14px;

      .el-radio {
        margin-bottom: 14px;

        .radio-custom-input {
          width: calc(100% - 28px);
        }
      }
    }

    .file-name {
      display: flex;
      width: 100%;
      border: 1px solid #dcdee2;
      border-radius: 2px;

      &>div {
        height: 28px;
        flex: 1;
        line-height: 28px;
      }

      .value-content {
        padding-left: 12px;
        display: inline-block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        word-break: keep-all;
        width: 100%;
      }

      .group-icon {
        color: #808695;
        text-align: center;
        padding: 0 7px;
        flex-grow: 0;
        flex-shrink: 0;
        cursor: pointer;

        &:hover {
          background: #ecf5ff;
        }
      }
    }

    .edit-button {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      justify-content: flex-start;

      .el-button {
        margin: 8px;
      }
    }

    .instance-container {
      height: 100%;

      ::v-deep .fileExplorerGroup {
        .el-tabs {
          .el-tabs__header {
            display: none;
          }

          .el-tabs__content {
            height: 100%;
          }
        }
      }
    }
  }

  .runInfo {
    &.form-container {
      .el-form-item {
        margin-bottom: 0;
      }
    }

    .node-desc {
      margin-top: 10px;
    }

    .algoInfo {
      margin-top: 10px;
    }
  }

  .text-align-center {
    text-align: center;
  }

  .operator-container {
    height: 100%;
  }
}

</style>
<style lang="scss">
.upload-file-name-tooltip {
  max-width: 400px;
  line-height: 2;
}
</style>
